package worker

import (
	"context"
	"encoding/json"
	"fmt"
	dto "github.com/prometheus/client_model/go"
	"gluenet/modules/strategies/iot-car/algorithm"
	"gluenet/modules/strategies/iot-car/data"
	"gluenet/modules/strategies/iot-car/prom"
	"gluenet/modules/strategies/iot-car/prom/metrics"
	v12 "gluenet/pkg/log/v1"
	"gluenet/pkg/nets"
	v1 "gluenet/utils/rpc/labels"
	"os"
	"strings"
	"time"
)

type Worker struct {
	ctx             context.Context
	collector       map[string]*prom.Collector
	algorithmCloser map[string]context.CancelFunc
}

func NewWorker(ctx context.Context) *Worker {
	return &Worker{
		ctx:             ctx,
		collector:       make(map[string]*prom.Collector),
		algorithmCloser: make(map[string]context.CancelFunc),
	}
}

func (r *Worker) Run(c nets.GlueNets, logger v12.Logger, data *data.Data) {
	var guarantGuid, besteffortGuid string
	for k := range data.BestApp {
		besteffortGuid = k
	}
	for k := range data.GuarantApp {
		guarantGuid = k
	}

	var ip = os.Getenv("OBJECT_HOST")
	var agent = os.Getenv("AGENT")
	// node
	//collector := prom.NewCollector(r.ctx, time.Second, fmt.Sprintf("http://%v:9100/metrics", ip))
	// container
	collector := prom.NewCollector(r.ctx, time.Second*2, fmt.Sprintf("http://%v:10001/metrics", ip))
	go collector.Run(logger)
	r.collector[ip] = collector

	// container
	ch, err := collector.AddLabel("container_cpu_usage_seconds_total", func(family *dto.MetricFamily) float64 {
		return metrics.GetContainerSpecialCpuMetricUsage(family, "cpu03", guarantGuid+"_car-back")
	})
	if err != nil {
		logger.Errorf("config colector %v", err)
		return
	}

	alg := algorithm.Simple(r.ctx, c, guarantGuid+"_car-back", besteffortGuid+"_cpu-interference", agent, ch)
	//alg := algorithm.Simple(r.ctx, c, guarantGuid, besteffortGuid, agent, ch)
	r.algorithmCloser[guarantGuid] = alg
}

func (r *Worker) Close() {
	for _, v := range r.collector {
		v.Close()
	}

	for _, colser := range r.algorithmCloser {
		colser()
	}
}

func getAgentIp(net nets.GlueNets, guid string) (map[string]interface{}, error) {
	req := map[string]interface{}{
		"data": guid,
	}
	bts, _ := json.Marshal(req)
	respBytes, err := net.Request(strings.Join([]string{v1.ControlManager, v1.InstanceAgentInfo}, ":"), bts)
	if err != nil {
		return nil, err
	}
	var resp interface{}
	if err = json.Unmarshal(respBytes, &resp); err != nil {
		return nil, err
	}
	d, ok := resp.(map[string]interface{})["data"]
	if !ok {
		return nil, fmt.Errorf("can't find data")
	}

	agentsMaps, ok := d.(map[string]interface{})["schedule_map"]
	if !ok {
		return nil, fmt.Errorf("can't find ip")
	}

	return agentsMaps.(map[string]interface{}), nil
}
